#include "../include/LRUCache.h"
#include <fstream>
#include <sstream>
#include <unistd.h>
#include <iostream>
#include <vector>
#include <string>

using std::string;
using std::vector;
using std::istringstream;
using std::ostringstream;
using std::ofstream;
using std::ifstream;
using std::cout;
using std::endl;
//将json写入到了磁盘
void LRUCache::readFromFile(const string& filename)
{
    ifstream ifs(filename.c_str());
    if(!ifs)
    {
        perror("ifs");
        return;
    }
    //读取一行到内存
    string line;
    while(getline(ifs,line))
    {
        //istringstream iss(line);
        //写入到缓存中
        string key;
        string tmp;
        //iss >> key >> tmp;
        int pos = line.find('[');
        key = line.substr(0,pos);
        tmp = line.substr(pos-1,line.size());
        //内存是json对象，磁盘是json字符串
        //提取问题，iss以空格作为分割，有可能提取到得字符串根本就不是json字符串得格式
        addRecord(key,json::parse(tmp));
    }
    ifs.close();
}

/*
 * LRU算法(最近最少使用):
 * 
 * */
void LRUCache::addRecord(string key, json js)
{
    //查看是否在缓存中存在
    auto it = _hashmap.find(key);
    if(it != _hashmap.end())
    {
        auto kit = it->second;
        //将其移动到头部即可
        _resultList.splice(_resultList.begin(),_resultList,kit);
        _hashmap.insert({key,_resultList.begin()});
        _resultList.begin()->second = js;
    }
    else
    {
        //添加进list中、并维护索引
        _resultList.insert(_resultList.begin(),std::make_pair(key,js));
        _hashmap.insert({key,_resultList.begin()});
        if(_resultList.size() > CACHE_CAPACITY)
        {
            //删除尾部的元素
            auto rearIt = _resultList.end();
            --rearIt;
            _hashmap.erase(rearIt->first);
            _resultList.pop_back();
        }
    }
}

//没实现
void LRUCache::update(const LRUCache& lru)
{
        //将lru缓存中得list链表得数据全部添加到当前缓存
        for(auto it = lru._resultList.begin(); it != lru._resultList.end(); it++)
        {
            addRecord(it->first,it->second);
        }
}   

void LRUCache::writeToFile(const string& filename)
{
    std::cout << "write to File" << std::endl;
    ofstream ofs(filename.c_str());
    if(!ofs)
    {
        perror("ofs");
        return;
    }
    
    for(auto it = _resultList.begin(); it != _resultList.end(); ++it)
    {
        // 写入到磁盘的是json字符串
       ofs << it->first << " " << it->second.dump() << std::endl; 
    }
    ofs.close();
}

/*
 * 根据_hashmap查找key对应的value,
 * 若存在:
 *      1.将改数据移动到链表的头部
 *      2.将json返回
 * 若不在:
 *      1.将<string,"nullptr">写入到缓存中
 *      2._hashmap记录他的位置
 * */
json LRUCache::doQuery(const string& key)
{
    auto it = _hashmap.find(key);
    if(it != _hashmap.end())
    {
        auto kit = it->second;
        //移动到头部
        _resultList.splice(_resultList.begin(),_resultList,kit);
        return kit->second;
    }
    else
    {
        //不存在，将key对应的nullptr添加到头部
        json js = vector<string>();
        addRecord(key,js);
        return js;
    }
}


void LRUCache::print_cache()
{
   for(auto it = _resultList.begin(); it != _resultList.end(); ++it)
   {
       std::cout << it->first << "  " << it->second.dump()  << std::endl;
   }
}
